﻿using System;
using System.Xml;
using System.Collections.Generic;
using System.Windows.Forms;
using SdmxMl.Helper;
using SdmxMl.Common;
using SdmxMl.Structure;
using SdmxMl.GenericMetadata;
using SdmxMl.Multiplexor;

namespace SdmxMl.Manager
{
    public class ReplaceRefMgr
    {
        private UrnParser upNewRef;
        private UrnParser upSourceRef;
        private SmManager sm;
        private List<ReferenceItem> targetedList;
        private ConceptSchemeType cstNew;
        private int replaceCount;

        public ReplaceRefMgr(UrnParser upSrc, UrnParser upRef, List<ReferenceItem> list, SmManager smMgr)
        {
            upSourceRef = upSrc;
            upNewRef = upRef;
            sm = smMgr;
            targetedList = list;

            // in case of replacement of full conceptScheme, load new one to be able to check
            // if concept ID in reference exists also in new conceptScheme
            if (upRef.ArType == SdmxArtefactType.Concepts && string.IsNullOrEmpty(upRef.SubTypeId))
                cstNew = sm.GetArtefact(upRef.ArType, upRef.TypedReference) as ConceptSchemeType;
        }

        public int ProcessReplace()
        {
            replaceCount = 0;
            foreach (ReferenceItem r in targetedList)
                if (r.Selected)
                {
                    UrnParser p = new UrnParser(r.Urn);
                    Artefact a = sm.GetArtefact(UrnManager.UrnToArtefactRefTyped(r.Urn));
                    if (a == null)
                        throw new ApplicationException("unable to locate artefact for : " + r.Urn);
                    // If a is finalised, do not operate but keep in info dico for later display
                    if (a.IsFinal == false)
                        ProdessItemReplace(a, p);
                }
            return replaceCount;

        }

        private void ProdessItemReplace(Artefact ar, UrnParser p)
        {
            if (ar != null && p != null && string.IsNullOrEmpty(p.SubType) == false)
            {
                string subType = p.SubType.ToLower();

                // Replace codelist reference in concept
                 if (subType == "concept")
                {
                    ConceptSchemeType cst = ar as ConceptSchemeType;
                    if (cst != null)
                    {
                        ConceptType c = cst.ConceptList.LocateItem(p.SubTypeId) as ConceptType;
                        if (c != null && upNewRef.ArType == SdmxArtefactType.CodeLists)
                        {
                            c.CoreRepresentation.AgencyId = upNewRef.AgencyId;
                            c.CoreRepresentation.Id = upNewRef.ArtefactId;
                            c.CoreRepresentation.Version = upNewRef.Version;
                            ++replaceCount;
                        }
                    }
                }

                 // Replace codelist reference in hierarchical Codelist
                 else if (subType == "codelistref" && upNewRef.ArType == SdmxArtefactType.CodeLists)
                 {
                     HierarchicalCodelistType hclt = ar as HierarchicalCodelistType;
                     foreach (CodelistRefType clrt in hclt.CodelistRefList)
                     {
                         if (clrt.FullIdent == upSourceRef.FullIdent)
                         {
                             clrt.AgencyId = upNewRef.AgencyId;
                             clrt.Id = upNewRef.ArtefactId;
                             clrt.Version = upNewRef.Version;
                             ++replaceCount;
                         }
                     }
                 }
                 // Replace codelist, conceptscheme or concept reference in DSD
                 else if (subType == "dimension" || subType == "attribute" || subType == "crosssectionalmeasure")
                 {
                     KeyFamilyType kft = ar as KeyFamilyType;
                     if (kft != null)
                     {
                         BaseDimensionType bd = kft.LocateItem(p.SubTypeId);
                         if (bd != null)
                         {
                             // Replace codelist reference
                             if (upNewRef.ArType == SdmxArtefactType.CodeLists)
                             {
                                 bd.CodelistInfo.AgencyId = upNewRef.AgencyId;
                                 bd.CodelistInfo.Id = upNewRef.ArtefactId;
                                 bd.CodelistInfo.Version = upNewRef.Version;
                                 ++replaceCount;
                             }
                             // Replace conceptscheme or concept reference 
                             else if (upNewRef.ArType == SdmxArtefactType.Concepts)
                             {
                                 if (string.IsNullOrEmpty(upNewRef.SubTypeId) == false &&
                                     string.IsNullOrEmpty(upSourceRef.SubTypeId) == false)
                                 {
                                     // Set if cannot verify or verified that new concept exists in scheme
                                     if (cstNew == null || cstNew.ConceptList.LocateItem(upNewRef.SubTypeId) != null)
                                        bd.ConceptInfo.Id = upNewRef.SubTypeId;
                                 }

                                 bd.ConceptSchemeInfo.Id = upNewRef.ArtefactId;
                                 bd.ConceptSchemeInfo.AgencyId = upNewRef.AgencyId;
                                 bd.ConceptSchemeInfo.Version = upNewRef.Version;
                                 ++replaceCount;

                             }
                         }
                     }
                 }

                 else if (subType == "reportstructure")
                 {
                     MetadataStructureDefinitionType msd = ar as MetadataStructureDefinitionType;
                     if (msd != null)
                     {
                         string[] arrR = p.SubTypeId.Split('.');
                         ReportStructureType report = null;
                         foreach (ReportStructureType rpt in msd.ReportStructureList)
                         {
                             if (rpt.Id == arrR[0])
                             {
                                 report = rpt;
                                 break;
                             }
                         }
                     }
                 }
                 else if (subType == "reportedattributetype")
                 {
                     MetadataSetType metaset = ar as MetadataSetType;
                     // locate row
                     foreach (AttributeValueSetType atv in metaset.AttributeValueSetList)
                     {
                         string[] arrKey = p.SubTypeId.Split('.');
                         // index 0 is report id, last index is refered concept id
                         if (arrKey.Length >= 3 && arrKey.Length == atv.TargetValuesTypeList.Count + 2)
                         {

                             string referedConceptId = arrKey[arrKey.Length - 1];
                             // Order reverted
                             List<string> listKey = new List<string>();
                             for (int key = arrKey.Length - 2; key > 0; --key)
                                 listKey.Add(arrKey[key]);

                             bool found = true;
                             for (int i = 0; i < listKey.Count; i++)
                             {
                                 if (atv.TargetValuesTypeList[i].Value != listKey[i])
                                 {
                                     found = false;
                                     break;
                                 }
                             }
                             if (found)
                             {
                                 ReportedAttributeTypeList repList = new ReportedAttributeTypeList();
                                 atv.ReportedAttributeList.GetReportedAttributeListForConcept(referedConceptId, repList);
                                 foreach (ReportedAttributeType rep in repList)
                                 {
                                     if (rep.Value.ToString() == upSourceRef.SubmittedUrn)
                                     {
                                         rep.Value.UpdateDefaultText(upNewRef.SubmittedUrn);
                                         ++replaceCount;

                                     }

                                 }
                             }
                         }
                         
                     }
                 }



/*
                else if (subType == "category")
                {
                    CategorySchemeType cst = ar as CategorySchemeType;
                    if (cst != null)
                        o = cst.CategoryList.LocateItemFromFullId(p.SubTypeId, cst.CategoryList);
                }
                else if (subType == "dimension")
                {
                    KeyFamilyType kft = ar as KeyFamilyType;
                    if (kft != null)
                        o = kft.DimensionList;
                }
                else if (subType == "attribute")
                {
                    KeyFamilyType kft = ar as KeyFamilyType;
                    if (kft != null)
                        o = kft.AttributeList;
                }
                else if (subType == "crosssectionalmeasure")
                {
                    KeyFamilyType kft = ar as KeyFamilyType;
                    if (kft != null)
                        o = kft.CrossSectionalMeasureList;
                }

              }
 * */

            }

        }
    }
}
